Skip to content

feat(my-account): group subscription management UX#4763

Closed
thomasguillot wants to merge 1 commit into
trunkfrom
feat/my-account-group-management
Closed

feat(my-account): group subscription management UX#4763
thomasguillot wants to merge 1 commit into
trunkfrom
feat/my-account-group-management

Conversation

@thomasguillot
Copy link
Copy Markdown
Contributor

@thomasguillot thomasguillot commented May 28, 2026

All Submissions:

Changes proposed in this Pull Request:

Adds end-to-end group subscription self-service in My Account. Owners can manage members and invites from a dedicated group page; members can leave a group; multi-group owners get a picker. Publishers can override the "group" terminology (singular + plural) per site.

Owner-facing

  • New /my-account/group/ endpoint. Single-group owners drop straight into management; multi-group owners see a card picker showing member count and subscription status.
  • Empty-state UI (centered card, stacked invite actions) when a group has no members and no invites.
  • Populated state uses a tabbed view (Members / Invitations) with per-row dropdown actions.
  • Remove member modal with member-specific copy and an "Are you sure?" confirmation heading.
  • Disable invite link modal now includes the "Are you sure?" heading, matching the pattern used by Leave group, Remove member, Delete account, and Cancel subscription.
  • Invitation row actions disambiguated: "Resend" → "Resend invite", "Cancel" → "Cancel invite".
  • Invite submit button shows a loading spinner during navigation.
  • Header "Invite members" dropdown only renders when the group has members or invites (suppressed in empty state).
  • Per-member join timestamps recorded and surfaced as "Member since" on the subscription details view.

Member-facing

  • Leave group flow on the subscription header, with a destructive confirm modal and loss-aversion copy.
  • Owner contact privacy: the subscription header shows the owner's display name only, not their email.
  • Orders and Payment information tabs are hidden for group members who have no orders of their own, removing empty-state noise from a member's My Account.

Newspack UI library

  • New tabs component (used by Members/Invitations view) with aria-selected / tabindex keyboard handling.
  • New __grid primitive — real CSS grid (was responsive flex on the old __row). Default 1 col mobile / 2 cols desktop. Modifiers: --cols-{3,4,5,6} for fixed column counts, --gap-{0..12} for the gap scale, and --subgrid for shared column tracks across child rows.
  • Box utility additions: --2x-large size modifier, :has(> __box__actions) semantic action layout, outline-button hover for anchor variants.
  • Dropdown rewritten with document-level event delegation so dropdowns inside tab panels (which the tabs controller restores on switch) keep working. Opening a dropdown now closes any other open one. New --align-start/center/end modifiers.
  • Modal form-submit handler now also catches nested <form> inside <section class="newspack-ui__modal__content">, not only the top-level case. Submit button labels wrapped in <span> so the loading spinner CSS works universally. Fetch-backed actions add the loading class to the button, not the span (prevents duplicate submits).
  • WC notice → Newspack snackbar conversion now handles WC Blocks markup (.wc-block-components-notice-banner.is-success) in addition to legacy .woocommerce-message.

Delete account modal

  • Modal sizes itself medium when the user has subscriptions / donations / newsletters to suggest, small otherwise.
  • Alternative-action rows (Subscriptions, Newsletters) refactored from the old __row + __width--40 layout into a __stack --horizontal per row, wrapped in a __grid --subgrid container so the action buttons align to the same column width regardless of label length.

Publisher controls (Audience → Setup)

  • "Group labels" override: publisher can set singular + plural terms (e.g. Team / Teams) that propagate through all reader-facing strings via Group_Subscription::get_label().

Utilities

  • newspack_get_user_display_label() in includes/util.php: strategy-driven cascade for resolving a user's display name.
  • New Group_Subscription_MyAccount::is_subscription_manageable() helper, used to derive the read-only state for cancelled/expired group subscriptions.

How to test the changes in this Pull Request:

Test using the QA seed at html/qa-seed-group-subs.php (run wp eval-file /var/www/html/qa-seed-group-subs.php). Password for every seeded user is password.

Owner — multi-group picker

  1. Log in as marcus.aldridge@example.com and visit /my-account/. Confirm a sidebar entry exists for the group endpoint.
  2. Click into it. With no subscription ID, the picker appears with two cards (one per group), each showing member count + status badge.
  3. Click a card. Lands on /my-account/group/{sub_id}/.

Owner — empty state

  1. Still as Marcus, clear members and invites from one of his groups (the family group), then visit that group's page.
  2. Confirm the centered empty-state box renders with three stacked actions (Invite by email, Copy invite link, Disable invite link is hidden until a link invite exists).
  3. The header "Invite members" dropdown is NOT shown in the empty state.

Owner — populated state

  1. Visit a populated group (e.g. Marcus's "Aldridge & Partners LLP", which the seed creates with custom name + 2 members + 1 invite). The tabs render with Members (3) / Invitations (1).
  2. Open the per-row dropdown on a non-manager member → click "Remove member". Modal opens with "Are you sure?" + the member's name. Confirm cancels.
  3. Switch to the Invitations tab. Open the row dropdown → see "Resend invite" / "Cancel invite" (was "Resend" / "Cancel"). Confirm "Cancel invite" submits directly without a modal.
  4. Open the header "Invite members" dropdown → "Disable invite link" → modal shows the header "Disable invite link" AND the body "Are you sure?" heading.

Owner — invite flow spinner

  1. From the empty state OR the header dropdown, click "Invite by email".
  2. Enter an email and submit. The submit button label disappears and a spinner animates in its place while the page navigates.
  3. After redirect, the WC notice is converted into a Newspack snackbar.

Member — leave group

  1. Log in as layla.shah@example.com (member of Imran's group).
  2. Visit /my-account/view-subscription/{imran_sub_id}/. Confirm the subscription header shows Imran's display name only (no email).
  3. Click "Leave group" → modal opens with "Are you sure?" + loss-aversion copy. Cancel closes the modal.

Member — hidden tabs

  1. Still as Layla, visit /my-account/. Navigation should NOT include Orders or Payment information (she's a group member with no orders of her own).
  2. Log in as a regular reader with orders (any seeded user with their own subscription) → both tabs appear.

Cancelled subscription owner

  1. Log in as hassan.khoury@example.com (cancelled group). Visit his group page.
  2. The "This group is no longer active…" info notice appears at the top, and management actions are suppressed.

Publisher label overrides

  1. As admin, visit Audience → Setup → Group labels.
  2. Override singular to "Team" + plural to "Teams". Save.
  3. Reload an owner's group page. All reader-facing strings now use "team"/"Teams" (button labels, modal copy, picker heading, empty-state copy, snackbar messages). The URL slug remains /group/ (this is intentional — see the discussion thread).

Member since timestamps

  1. As Marcus, manage a populated group. Each member row's tooltip/detail surfaces a "Member since" date relative to when they joined.
  2. Add a new member via invite → join timestamp is written when the invite is accepted.

Delete account modal

  1. Log in as eleanor.whitfield@example.com (she owns 1 active subscription).
  2. My Account → Account details → "Delete my account" → modal opens at medium size.
  3. Confirm: "Are you sure?" heading, body copy, then one or more alternative-action rows. The "Manage X" buttons align to the same column width across rows (subgrid).
  4. Log in as a reader with no subscriptions / donations / newsletters → same modal opens at small size with no alternative rows.

Other information:

  • Have you added an explanation of what your changes do and why you'd like us to include them?
  • Have you written new tests for your changes, as applicable?
  • Have you successfully ran tests with your changes locally?

@thomasguillot thomasguillot requested a review from Copilot May 28, 2026 15:51
@github-actions
Copy link
Copy Markdown

👋 Thanks for your interest in contributing to Newspack!

Newspack development has moved to a single monorepo: Automattic/newspack-workspace. This repository is now a read-only mirror, so we're automatically closing new pull requests here.

Please reopen your change against the monorepo – newspack-plugin now lives at plugins/newspack-plugin/ there. Thank you! 💙

@github-actions github-actions Bot closed this May 28, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds end-to-end group subscription self-service to My Account: a new /group/ endpoint with single-group auto-redirect and a multi-group picker, member self-leave flow, publisher-configurable group label (singular/plural) wired through Audience → Setup, per-member join timestamps, and a member-friendly subscription view that hides financial details. Ships supporting Newspack UI library work (new tabs primitive shared with segmented-control, __row__grid layout rename, dropdown rewrite using event delegation, modal/button loading-state improvements) and a member-aware menu that hides Orders/Payment information for group-only members.

Changes:

  • Owner-facing group management UI (group.php, picker, tabbed members/invitations panel, remove-member confirm modal, manageability gating for cancelled/expired subs) and LEAVE_GROUP_NONCE_ACTION self-removal flow.
  • Publisher label override (Group_Subscription::get_label, REST endpoints, Audience wizard Groups tab) propagated through every reader-facing string and the sidebar entry.
  • Newspack UI tabs component extracted from segmented-control, dropdown rewrite via document-level delegation, modal nested-form submit handling, newspack-ui__rownewspack-ui__grid rename with new gap modifiers.

Reviewed changes

Copilot reviewed 45 out of 45 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
includes/plugins/woocommerce-subscriptions/group-subscription/class-group-subscription.php Adds join-timestamp meta, get_label(), and get_managed_subscriptions_for_user().
includes/plugins/woocommerce-subscriptions/group-subscription/class-group-subscription-myaccount.php New group endpoint, picker/landing resolver, manageability + leave-group handlers, legacy 308 redirect.
includes/plugins/woocommerce-subscriptions/group-subscription/class-group-subscription-settings.php Name fallback now product-name → singular label; registers label options.
includes/plugins/woocommerce/my-account/class-my-account-ui-v1.php Group sidebar entry, dead-end Orders/Payment redirects, template map for new templates.
includes/plugins/woocommerce/my-account/class-woocommerce-my-account.php Reorders top-of-menu items to include newsletters.
includes/plugins/woocommerce/my-account/templates/v1/group.php New group page shell with header + invite-members dropdown.
includes/plugins/woocommerce/my-account/templates/v1/group-picker.php New multi-group picker card layout.
includes/plugins/woocommerce/my-account/templates/v1/group-subscription-members.php Empty state, tabs markup, manageable gating, remove-member modal, label-aware copy.
includes/plugins/woocommerce/my-account/templates/v1/subscription-header.php Member leave-group button + modal; status badge always rendered.
includes/plugins/woocommerce/my-account/templates/v1/subscription-details.php Hides financials for members, adds "Member since" and group-name rows.
includes/plugins/woocommerce/my-account/templates/v1/view-subscription.php Skips totals/related-orders for members.
includes/plugins/woocommerce/my-account/templates/v1/payment-information.php Switches layout primitives to __grid, refactors empty/populated address rendering.
includes/plugins/woocommerce/my-account/templates/v1/my-subscriptions.php Uses Group_Subscription::get_label() for group badge.
includes/wizards/audience/class-audience-wizard.php New REST endpoints for group label settings.
includes/util.php New newspack_get_user_display_label() cascade helper.
includes/class-newspack-ui.php Wraps modal action labels in <span>; demo content for new tabs.
includes/class-newspack-ui-icons.php Adds lineSolid icon.
src/wizards/audience/views/setup/index.js Registers Advanced settings tab/route.
src/wizards/audience/views/setup/groups.js New screen wrapping GroupLabels.
src/wizards/audience/components/group-labels/index.js New singular/plural label form.
src/newspack-ui/js/utils/index.js Adds shared setupTabController.
src/newspack-ui/js/tabs/index.js New tabs init.
src/newspack-ui/js/segmented-control/index.js Reuses shared controller.
src/newspack-ui/js/modals.js Adds loading state on submit; covers nested forms.
src/newspack-ui/js/dropdowns.js Rewritten with document-level delegation.
src/newspack-ui/js/index.js Imports tabs module.
src/newspack-ui/scss/elements/_layout.scss Renames __row to __grid with new gap modifiers.
src/newspack-ui/scss/elements/_tabs.scss / _index.scss New tabs SCSS.
src/newspack-ui/scss/elements/_boxes.scss --2x-large size, :has(> __actions) semantic.
src/newspack-ui/scss/elements/misc/_dropdown.scss --align-start/center/end modifiers.
src/newspack-ui/scss/elements/forms/_buttons.scss Icon margin tweak for --line-solid.
src/newspack-ui/scss/elements/woocommerce/_my-account.scss Table border/spacing/min-height; updates renamed class.
src/my-account/v1/index.js, global.js, subscriptions.js, group-subscriptions.js Leave-group modal trigger; WC Blocks notice → snackbar; remove-member delegation; drops badge sync.
src/my-account/v1/style.scss, _group.scss, _group-subscriptions.scss, _subscriptions.scss Empty-state/picker styling, compact subscription header buttons.
tests/unit-tests/content-gate/group-management-nav.php New tests covering label helper, managed subs, endpoint, picker, menu.
tests/unit-tests/plugins/woocommerce-subscriptions/group-subscription/class-group-subscription-myaccount.php Manageability + leave-group test coverage; manager-actions pass-through.
tests/unit-tests/plugins/woocommerce-subscriptions/group-subscription/class-group-subscription-settings.php Name-fallback tests updated to product-name → singular label.
tests/unit-tests/content-gate/group-subscriptions.php Updates fallback expectations to singular label.
tests/mocks/wc-mocks.php Adds customer/subscription getters, status name, template map, filter application.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/newspack-ui/scss/elements/_layout.scss
Comment thread src/my-account/v1/group-subscriptions.js
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants